import { useState, useEffect, useRef } from "react";

export const isFalsy = (value: unknown) => (value === 0 ? false : !value);

export const isVoid = (value: unknown) =>
    value === undefined || value === null || value === "";

// 在一个函数里，改变传入的对象本身是不好的
export const cleanObject = (object: { [key: string]: unknown }) => {
    // Object.assign({}, object)
    const result = { ...object };
    Object.keys(result).forEach((key) => {
        const value = result[key];
        if (isVoid(value)) {
            delete result[key];
        }
    });
    return result;
};

export const useMount = (callback: () => void) => {
    useEffect(() => {
        callback();
        //  eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);
};

// export const useDebounce = <T>(value: T, delay?: number): => {
//     const [debouncedValue, setDebouncedValue] = useState(value);
//
//     useEffect(() => {
//         const timeout = setTimeout(() => setDebouncedValue(value), delay);
//         return () => clearTimeout(timeout);
//     }, [value, delay]);
//
//     return debouncedValue;
// };

export const useDebounce = <V>(value: V, delay?: number) => {
    const [debouncedValue, setDebouncedValue] = useState(value);

    useEffect(() => {
        // 每次在value变化以后，设置一个定时器
        const timeout = setTimeout(() => setDebouncedValue(value), delay);
        // 每次在上一个useEffect处理完以后再运行
        return () => clearTimeout(timeout);
    }, [value, delay]);

    return debouncedValue;
};

// home work
export const useArray = <T>(initialArray: T[]) => {
    // useState 来给组件内部添加一些state,react会在重复渲染时保留这个state,
    // 唯一的参数就是初始state，不需要是一个对象，如果你有需要，它也可以是，这个初始state参数只有在第一次渲染时才会被用到
    // 会返回一对值，当前状态和一个让你更新它的函数，你可以在事件处理函数中或者其他地方调用这个函数
    // 它不会把新的state和旧的state进行合并
    const [value, setValue] = useState(initialArray);
    return {
        value,
        setValue,
        add: (item: T) => setValue([...value, item]),
        clear: setValue([]),
        removeIndex: (index: number) => {
            const copy = [...value];
            copy.splice(index);
            setValue(copy);
        },
    };
};

// 利用useRef和useEffect写一个自定义hook useDocumentTitle来动态改变我们的页面标题
export const useDocumentTitle = (title: string, keepOnUnmount = true) => {
    const oldTitle = useRef(document.title).current;
    useEffect(() => {
        document.title = title;
    }, [title]);

    useEffect(() => {
        return () => {
            if (!keepOnUnmount) {
                document.title = oldTitle;
            }
        };
    }, [keepOnUnmount, oldTitle]);
};

export const resetRoute = () => (window.location.href = window.location.origin);

export const subset = <
    O extends { [key in string]: unknown },
    K extends keyof O
>(
    obj: O,
    keys: K[]
) => {
    const filteredEntries = Object.entries(obj).filter(([key]) =>
        keys.includes(key as K)
    );
    return Object.fromEntries(filteredEntries) as Pick<O, K>;
};

// 返回组件的挂载状态，如果还没有挂载或者已经卸载，返回false，反之，返回true
// 阻止了在已卸载组件上赋值
export const useMountedRef = () => {
    const mountedRef = useRef(false);
    // 页面加载完了以后调用 所以设置为true
    useEffect(() => {
        mountedRef.current = true;
        return () => {
            // 被卸载的时候设置为false
            mountedRef.current = false;
        };
    });
    return mountedRef;
};
